package com.pipe.protocol.login;

import com.pipe.util.*;
import io.netty.buffer.ByteBuf;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * @author Kiven
 */
public class InitialHandshakePacket {
    private static Logger LOG = LoggerFactory.getLogger(InitialHandshakePacket.class);

    private short version;
    private String serverVersion;
    /**a.k.a. connection id*/
    private long threadId;

    private short characterSet;
    private int statusFlags;

    private String authPluginName;

    /**计算出的结果*/
    private int capabilityFlags;
    private byte[] seed;

    public InitialHandshakePacket(short version, String serverVersion, long threadId, short characterSet, int statusFlags,
                                  int capabilityFlags, String authPluginName, byte[] seed) {
        this.version = version;
        this.serverVersion = serverVersion;
        this.threadId = threadId;
        this.characterSet = characterSet;
        this.statusFlags = statusFlags;
        this.capabilityFlags = capabilityFlags;
        this.authPluginName = authPluginName;
        this.seed = seed;
    }

    public static InitialHandshakePacket build(short version, String serverVersion, long threadId, short characterSet, int statusFlags,
                                               int capabilityFlags, String authPluginName, byte[] seed){
        return new InitialHandshakePacket(version, serverVersion, threadId, characterSet, statusFlags, capabilityFlags, authPluginName, seed);
    }

//    public static InitialHandshakePacket build(byte[] data) throws Exception {
//        PipeNumber index = PipeNumber.ZERO();
//        byte version = ByteArrayUtil.getByteFromData(1, data, index)[0];
//
//        int nullTailIndex = ByteArrayUtil.getNullTailIndex(data, index.get());
//        int serverVersionArrLen = nullTailIndex - index.get();
//        byte[] serverVersionArr = ByteArrayUtil.getByteFromData(serverVersionArrLen, data, index);
//
//        index.reSet(nullTailIndex + 1);
//
//        byte[] thredIdArr = ByteArrayUtil.getByteFromData(4, data, index);
//        int thredId = ByteArrayConveter.getInt(thredIdArr, 0);
//
//        byte[] authPluginDataPrartOneArr = ByteArrayUtil.getByteFromData(8, data, index);
//
//        /**skip filler*/
//        byte filler = ByteArrayUtil.getByteFromData(1, data, index)[0];
//
//        byte[] capabilityFlagsOneArr = ByteArrayUtil.getByteFromData(2, data, index);
//
//        byte characterSet = ByteArrayUtil.getByteFromData(1, data, index)[0];
//
//        byte[] statusFlagsArr = ByteArrayUtil.getByteFromData(2, data, index);
//        short statusFlags = ByteArrayConveter.getShort(statusFlagsArr, 0);
//
//        byte[] capabilityFlagsTwoArr = ByteArrayUtil.getByteFromData(2, data, index);
//
//        int capabilityFlags = ByteArrayConveter.getInt(ByteArrayUtil.merge2Arr(capabilityFlagsOneArr, capabilityFlagsTwoArr), 0);
//
//        byte authPluginDataLen = ByteArrayUtil.getByteFromData(1, data, index)[0];
//
//        byte[] reservedArr = ByteArrayUtil.getByteFromData(10, data, index);
//
//        byte[] authPluginDataPartTwoArr = null;
//        byte[] authPluginNameArr = null;
//        if ((capabilityFlags & CapabilitiesFlags.CLIENT_PLUGIN_AUTH) == CapabilitiesFlags.CLIENT_PLUGIN_AUTH){
//            authPluginDataPartTwoArr = ByteArrayUtil.getByteFromData((int)authPluginDataLen, data, index);
//            int authPluginNameArrLen = data.length - index.get() - 1;
//            authPluginNameArr = ByteArrayUtil.getByteFromData(authPluginNameArrLen, data, index);
//        }
//        return InitialHandshakePacket.build(version, serverVersionArr, thredId, authPluginDataPrartOneArr, filler, capabilityFlagsOneArr,
//                characterSet, statusFlags, capabilityFlagsTwoArr, capabilityFlags, authPluginDataLen, reservedArr, authPluginDataPartTwoArr, authPluginNameArr);
//    }

    public static InitialHandshakePacket build(ByteBuf byteBuf) throws Exception {
        short version = byteBuf.readUnsignedByte();

        byte[] serverVersionArr = MysqlProtocolUtil.getNullTailBytes(byteBuf);

        long thredId = byteBuf.readUnsignedIntLE();

        byte[] authPluginDataPrartOneArr = new byte[8];
        byteBuf.readBytes(authPluginDataPrartOneArr);

        /**skip filler*/
        byteBuf.skipBytes(1);

        byte[] capabilityFlagsOneArr = new byte[2];
        byteBuf.readBytes(capabilityFlagsOneArr);

        short characterSet = byteBuf.readUnsignedByte();

        int statusFlags = byteBuf.readUnsignedShortLE();

        byte[] capabilityFlagsTwoArr = new byte[2];
        byteBuf.readBytes(capabilityFlagsTwoArr);

        int capabilityFlags = IntegerConveter.getInt(MysqlProtocolUtil.merge2Arr(capabilityFlagsOneArr, capabilityFlagsTwoArr));

        short authPluginDataLen = byteBuf.readUnsignedByte();

        /**skip filler*/
        byteBuf.skipBytes(10);

        byte[] authPluginDataPartTwoArr = null;
        String authPluginName= null;
        byte[] seed = null;
        if ((capabilityFlags & CapabilitiesFlags.CLIENT_PLUGIN_AUTH) == CapabilitiesFlags.CLIENT_PLUGIN_AUTH){
            int length = 13 > (authPluginDataLen - 8) ? 13 : authPluginDataLen - 8;
            authPluginDataPartTwoArr = new byte[length];
            byteBuf.readBytes(authPluginDataPartTwoArr);
            byte[] authPluginNameArr = new byte[byteBuf.readableBytes()];
            byteBuf.readBytes(authPluginNameArr, 0, authPluginNameArr.length);
            authPluginName = new String(authPluginNameArr);
            seed = MysqlProtocolUtil.merge2seed(authPluginDataPrartOneArr, authPluginDataPartTwoArr);
        }
        return InitialHandshakePacket.build(version, new String(serverVersionArr), thredId, characterSet, statusFlags, capabilityFlags, authPluginName, seed);
    }

    public byte[] getSeed() {
        return seed;
    }

    public short getCharacterSet() {
        return characterSet;
    }
}